<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="keywords" content="imlgw,半岛铁盒,blog,Java博客,程序员,个人博客,java開發,程序員,個人博客,Java">
    <meta name="description" content="大悲无泪，大悟无言，大笑无声。">
    <meta name="author" content="Resolmi">
    
    <title>
        
            CAS与原子变量 |
        
        Tadow
    </title>
    
<link rel="stylesheet" href="/css/style.css">

    <link rel="shortcut icon" href="https://static.imlgw.top/blog/20210731/BtJz541CcmJU.ico">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/css/font-awesome.min.css">
    <script id="hexo-configurations">
    let KEEP = window.KEEP || {};
    KEEP.hexo_config = {"hostname":"imlgw.top","root":"/","language":"zh-CN","path":"search.json"};
    KEEP.theme_config = {"toc":{"enable":true,"number":true,"expand_all":true,"init_open":true},"style":{"primary_color":"#0066CC","avatar":"https://static.imlgw.top/blog/20210731/3C7hCSRR3lfq.png","favicon":"https://static.imlgw.top/blog/20210731/BtJz541CcmJU.ico","article_img_align":"left","left_side_width":"260px","content_max_width":"920px","hover":{"shadow":false,"scale":true},"first_screen":{"enable":true,"background_img":"/images/image.svg","description":"Keep It Simple & Stupid."},"scroll":{"progress_bar":{"enable":true},"percent":{"enable":true}}},"local_search":{"enable":true,"preload":false},"code_copy":{"enable":true,"style":"default"},"pjax":{"enable":true},"lazyload":{"enable":true},"version":"3.4.3"};
    KEEP.language_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 月前","year":"%s 年前"};
  </script>
<meta name="generator" content="Hexo 5.4.0"><link rel="stylesheet" href="/css/prism.css" type="text/css"></head>


<body>
<div class="progress-bar-container">
    
        <span class="scroll-progress-bar"></span>
    

    
        <span class="pjax-progress-bar"></span>
        <span class="pjax-progress-icon">
            <i class="fas fa-circle-notch fa-spin"></i>
        </span>
    
</div>


<main class="page-container">

    

    <div class="page-main-content">

        <div class="page-main-content-top">
            <header class="header-wrapper">

    <div class="header-content">
        <div class="left">
            
            <a class="logo-title" href="/">
                Tadow
            </a>
        </div>

        <div class="right">
            <div class="pc">
                <ul class="menu-list">
                    
                        <li class="menu-item">
                            <a class=""
                               href="/"
                            >
                                首页
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/archives"
                            >
                                归档
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/categories"
                            >
                                分类
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/sbe"
                            >
                                订阅
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/links"
                            >
                                友链
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/about"
                            >
                                关于
                            </a>
                        </li>
                    
                    
                        <li class="menu-item search search-popup-trigger">
                            <i class="fas fa-search"></i>
                        </li>
                    
                </ul>
            </div>
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fas fa-search"></i></div>
                
                <div class="icon-item menu-bar">
                    <div class="menu-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <div class="header-drawer">
        <ul class="drawer-menu-list">
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/">首页</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/archives">归档</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/categories">分类</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/sbe">订阅</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/links">友链</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/about">关于</a>
                </li>
            
        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="page-main-content-middle">

            <div class="main-content">

                
                    <div class="fade-in-down-animation">
    <div class="article-content-container">

        <div class="article-title">
            <span class="title-hover-animation">CAS与原子变量</span>
        </div>

        
            <div class="article-header">
                <div class="avatar">
                    <img src="https://static.imlgw.top/blog/20210731/3C7hCSRR3lfq.png">
                </div>
                <div class="info">
                    <div class="author">
                        <span class="name">Resolmi</span>
                        
                            <span class="author-label">BOSS</span>
                        
                    </div>
                    <div class="meta-info">
                        <div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fas fa-edit"></i>&nbsp;2019-04-22 00:00:00
    </span>
    
        <span class="article-categories article-meta-item">
            <i class="fas fa-folder"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/categories/%E5%B9%B6%E5%8F%91/">并发</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fas fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/">多线程</a>&nbsp;
                    </li>
                
                    <li>
                        | <a href="/tags/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">并发编程</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
        <span class="article-wordcount article-meta-item">
            <i class="fas fa-file-word"></i>&nbsp;<span>3.6k 字</span>
        </span>
    
    
        <span class="article-min2read article-meta-item">
            <i class="fas fa-clock"></i>&nbsp;<span>16 分钟</span>
        </span>
    
    
        <span class="article-pv article-meta-item">
            <i class="fas fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

                    </div>
                </div>
            </div>
        

        <div class="article-content markdown-body">
            <h2 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h2><p><em>这个<strong>CAS</strong>可不是单点登陆的那个CAS😄!!!</em></p>
<blockquote>
<p>CAS（Compare-and-Swap），是对一种处理器指令的称呼，很多Java多线程相关的类库的最终实现都会借助CAS</p>
</blockquote>
<p>​    从所周知，类似<code>i++</code>自增这样的操作并不是原子的，是一个<code>read-modify-write</code>的操作 ，如果要保证这种操作的原子性按照之前的做法可以使用<code>synchronized</code>内部锁来解决，但是这样似乎有点太小题大做了，锁确实可以解决这个问题，但是前面的文章也提到过，锁是很消耗性能的，并不是最好的做法，比较好的做法就是<strong>CAS</strong>，它能够将这些操作转换为原子操作。</p>
<p>​    Compare and Swap，比较并交换，顾名思义是一种<code>if-then-act</code>的操作，而这个操作的原子性由<code>处理器</code>保证(硬件锁)，如果一个线程想要将变量V的值由A变为B，借助CAS就会产生类似下面代码的作用</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">boolean</span> <span class="title">comapreAndSet</span><span class="params">(Variable V,Object A,Objext B)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(V.get()==A)&#123; <span class="comment">//判断是否和当前V的值相同（是否被修改）</span></span><br><span class="line">        V.set(B);   <span class="comment">//没被修改就更新</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>; <span class="comment">//被修改过就直接return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样一来就是先下手为强了，当你最先修改了V的值，后面的所有线程都会直接失败，所以实际上也是一种快速失败策略，当然你也可以尝试再次请求直到成功为止。</p>
<h2 id="原子变量类"><a href="#原子变量类" class="headerlink" title="原子变量类"></a>原子变量类</h2><p>_原子变量类_是基于CAS实现的一组保证共享变量<code>read-modify-write</code>操作(例如自增)原子性的工具类</p>
<table>
<thead>
<tr>
<th>分组</th>
<th>类</th>
</tr>
</thead>
<tbody><tr>
<td>基础数据类型</td>
<td>AtomicInteger，AtomicLong，AtomicBoolean</td>
</tr>
<tr>
<td>数组类</td>
<td>AtomicIntegerArray，AtomicLongArray，AtomicReferenceArray</td>
</tr>
<tr>
<td>字段更新器</td>
<td>AtomicIntegerFieldUpdater，AtomicLongFieldUpdater，AtomicReferenceFieldUpdater</td>
</tr>
<tr>
<td>引用型</td>
<td>AtomicReference，AtomicStampedReference，AtomicMarkableReference</td>
</tr>
</tbody></table>
<p>关于怎么使用就不多介绍，API上都写的明明白白，这里有个地方需要注意，数组类单纯的GET/SET并不是原子操作。</p>
<h3 id="利用CAS写一个锁"><a href="#利用CAS写一个锁" class="headerlink" title="利用CAS写一个锁"></a>利用CAS写一个锁</h3><p><a href="http://imlgw.top/2019/04/07/java-duo-xian-cheng-xue-xi-bi-ji/">前面的文章</a>  利用内部锁实现过一个<strong>BooleanLock</strong>，这里利用CAS再实现一个简易的锁</p>
<p><strong>getLockException</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GetLockException</span> <span class="keyword">extends</span> <span class="title">Exception</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">GetLockException</span><span class="params">(String message)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">GetLockException</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>CASLock</strong> </p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CASLock</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> AtomicInteger value = <span class="keyword">new</span> AtomicInteger();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Thread lockedThread;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">trylock</span><span class="params">()</span> <span class="keyword">throws</span> GetLockException </span>&#123;</span><br><span class="line">        <span class="keyword">boolean</span> success = value.compareAndSet(<span class="number">0</span>, <span class="number">1</span>);</span><br><span class="line">        <span class="keyword">if</span> (!success) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> GetLockException(<span class="string">&quot;获得锁失败&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        lockedThread = Thread.currentThread();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">unlock</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="number">0</span> == value.get()) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (lockedThread == Thread.currentThread()) &#123;</span><br><span class="line">            <span class="comment">//解铃还须系铃人</span></span><br><span class="line">            <span class="keyword">boolean</span> success = value.compareAndSet(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot; 释放了锁&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其实挺简单的，值得注意的地方就是释放锁的时候别忘了判断是不是当前线程加的锁，解铃还须系铃人😂</p>
<h3 id="ABA问题"><a href="#ABA问题" class="headerlink" title="ABA问题"></a>ABA问题</h3><blockquote>
<p>从所周知，CAS成立的条件就是共享变量当前值和当前线程所提供的旧值相同，我们就可以认为这个变量没有被修改过，那么问题来了，对于一个共享变量<strong>V</strong>，如果当前线程看到它的时候它的值是A，当它想执行CAS修改这个变量的时候，另一个线程将<strong>V</strong>的值从A–&gt;B–&gt;A，那么这时当前线程再来执行CAS的时候，是否可以认为变量<strong>V</strong>没有被修改过呢？这里执行肯定是会成功的，但是这样结果是否可以接受呢 ?</p>
</blockquote>
<h4 id="无法接受的例子"><a href="#无法接受的例子" class="headerlink" title="无法接受的例子"></a>无法接受的例子</h4><p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top///20190423/vakfPgUQChGb.png?imageslim"
                      alt="mark"
                ></p>
<p>上图为用<strong>单链表</strong>实现的栈结构，若T2先抢到了执行权，将A，B弹出栈，然后依次<code>push</code>了D，C，A，然后T1执行，利用CAS，head.compareAndSet(A，B)，执行成功，栈顶变为B，然而B就是个孤儿节点，这样一来C，D节点就被莫名其妙被丢掉了这显然是有问题的</p>
<h4 id="如何解决ABA问题"><a href="#如何解决ABA问题" class="headerlink" title="如何解决ABA问题"></a>如何解决ABA问题</h4><p>其实ABA问题并非完全无法接受，要考虑具体的场景，当然Java中也提供了解决的方案:</p>
<p><code>AtomicStampedReference</code> 这个类看名字就知道是带了戳的，带了一个类似版本号的东西，直接上源码吧。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AtomicStampedReference</span>&lt;<span class="title">V</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Pair</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line">        <span class="keyword">final</span> T reference;</span><br><span class="line">        <span class="keyword">final</span> <span class="keyword">int</span> stamp;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> <span class="title">Pair</span><span class="params">(T reference, <span class="keyword">int</span> stamp)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.reference = reference;</span><br><span class="line">            <span class="keyword">this</span>.stamp = stamp;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">static</span> &lt;T&gt; <span class="function">Pair&lt;T&gt; <span class="title">of</span><span class="params">(T reference, <span class="keyword">int</span> stamp)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> Pair&lt;T&gt;(reference, stamp);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Pair&lt;V&gt; pair;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">AtomicStampedReference</span><span class="params">(V initialRef, <span class="keyword">int</span> initialStamp)</span> </span>&#123;</span><br><span class="line">        pair = Pair.of(initialRef, initialStamp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Returns the current value of the reference.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the current value of the reference</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">getReference</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> pair.reference;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getStamp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> pair.stamp;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> V <span class="title">get</span><span class="params">(<span class="keyword">int</span>[] stampHolder)</span> </span>&#123;</span><br><span class="line">        Pair&lt;V&gt; pair = <span class="keyword">this</span>.pair;</span><br><span class="line">        stampHolder[<span class="number">0</span>] = pair.stamp;</span><br><span class="line">        <span class="keyword">return</span> pair.reference;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">weakCompareAndSet</span><span class="params">(V   expectedReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                     V   newReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                     <span class="keyword">int</span> expectedStamp,</span></span></span><br><span class="line"><span class="params"><span class="function">                                     <span class="keyword">int</span> newStamp)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> compareAndSet(expectedReference, newReference,</span><br><span class="line">                             expectedStamp, newStamp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Atomically sets the value of both the reference and stamp</span></span><br><span class="line"><span class="comment">     * to the given update values if the</span></span><br><span class="line"><span class="comment">     * current reference is &#123;<span class="doctag">@code</span> ==&#125; to the expected reference</span></span><br><span class="line"><span class="comment">     * and the current stamp is equal to the expected stamp.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> expectedReference the expected value of the reference</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> newReference the new value for the reference</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> expectedStamp the expected value of the stamp</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> newStamp the new value for the stamp</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if successful</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">compareAndSet</span><span class="params">(V   expectedReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 V   newReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 <span class="keyword">int</span> expectedStamp,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 <span class="keyword">int</span> newStamp)</span> </span>&#123;</span><br><span class="line">        Pair&lt;V&gt; current = pair;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">            expectedReference == current.reference &amp;&amp; <span class="comment">//期望值和当前值相等</span></span><br><span class="line">            expectedStamp == current.stamp &amp;&amp;	<span class="comment">//期望的戳和当前的戳一致</span></span><br><span class="line">            ((newReference == current.reference &amp;&amp; <span class="comment">//新的值是不是和当前的值一样</span></span><br><span class="line">              newStamp == current.stamp) ||		<span class="comment">//新的戳是不是和当前的戳一样</span></span><br><span class="line">             casPair(current, Pair.of(newReference, newStamp))); <span class="comment">//如果不一样就利用CAS设置新值</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">set</span><span class="params">(V newReference, <span class="keyword">int</span> newStamp)</span> </span>&#123;</span><br><span class="line">        Pair&lt;V&gt; current = pair;</span><br><span class="line">        <span class="keyword">if</span> (newReference != current.reference || newStamp != current.stamp)</span><br><span class="line">            <span class="keyword">this</span>.pair = Pair.of(newReference, newStamp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">attemptStamp</span><span class="params">(V expectedReference, <span class="keyword">int</span> newStamp)</span> </span>&#123;</span><br><span class="line">        Pair&lt;V&gt; current = pair;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">            expectedReference == current.reference &amp;&amp;</span><br><span class="line">            (newStamp == current.stamp ||</span><br><span class="line">             casPair(current, Pair.of(expectedReference, newStamp)));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Unsafe mechanics 底层调用unsafe的方法</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> pairOffset =objectFieldOffset(UNSAFE, <span class="string">&quot;pair&quot;</span>, AtomicStampedReference.class);</span><br><span class="line">    <span class="comment">//cas设置新值</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">boolean</span> <span class="title">casPair</span><span class="params">(Pair&lt;V&gt; cmp, Pair&lt;V&gt; val)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> UNSAFE.compareAndSwapObject(<span class="keyword">this</span>, pairOffset, cmp, val);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">long</span> <span class="title">objectFieldOffset</span><span class="params">(sun.misc.Unsafe UNSAFE,</span></span></span><br><span class="line"><span class="params"><span class="function">                                  String field, Class&lt;?&gt; klazz)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (NoSuchFieldException e) &#123;</span><br><span class="line">            <span class="comment">// Convert Exception to corresponding Error</span></span><br><span class="line">            NoSuchFieldError error = <span class="keyword">new</span> NoSuchFieldError(field);</span><br><span class="line">            error.initCause(e);</span><br><span class="line">            <span class="keyword">throw</span> error;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>这里删掉了部分注释， 可以看到里面封装了一个<code>Pair</code>里面有对象的引用和一个戳，在进行CAS的时候会判断<code>期望的引用</code>（传进来的引用）和<code>当前实际的引用</code>是不是一致，<code>期望的戳</code>（传进来的戳）和<code>当前实际的戳</code>是不是一致的，不一致就会直接<code>fail</code>，关键的CAS代码：</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">compareAndSet</span><span class="params">(V   expectedReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 V   newReference,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 <span class="keyword">int</span> expectedStamp,</span></span></span><br><span class="line"><span class="params"><span class="function">                                 <span class="keyword">int</span> newStamp)</span> </span>&#123;</span><br><span class="line">        Pair&lt;V&gt; current = pair;</span><br><span class="line">        <span class="keyword">return</span>  </span><br><span class="line">            expectedReference == current.reference &amp;&amp; <span class="comment">//期望值和当前值相等</span></span><br><span class="line">            expectedStamp == current.stamp &amp;&amp;	<span class="comment">//期望的戳和当前的戳一致</span></span><br><span class="line">            ((newReference == current.reference &amp;&amp; <span class="comment">//新的值是不是和当前的值一样</span></span><br><span class="line">              newStamp == current.stamp) ||		<span class="comment">//新的戳是不是和当前的戳一样</span></span><br><span class="line">             casPair(current, Pair.of(newReference, newStamp))); <span class="comment">//如果不一样就利用CAS设置新值</span></span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p><strong>测试AtomicStampedReference</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AtomicRefStampedTest</span> </span>&#123;</span><br><span class="line">   <span class="keyword">static</span> AtomicStampedReference&lt;Integer&gt; reference=<span class="keyword">new</span> AtomicStampedReference&lt;&gt;(<span class="number">100</span>,<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//第一个线程进行ABA操作</span></span><br><span class="line">        <span class="keyword">new</span> Thread(()-&gt;&#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">1</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;t1 &quot;</span>+reference.compareAndSet(<span class="number">100</span>, <span class="number">101</span>, reference.getStamp(), reference.getStamp()+<span class="number">1</span>));</span><br><span class="line">                System.out.println(reference.getStamp()+<span class="string">&quot;,&quot;</span>+reference.getReference());</span><br><span class="line">                System.out.println(<span class="string">&quot;t1 &quot;</span>+ reference.compareAndSet(<span class="number">101</span>, <span class="number">100</span>,reference.getStamp() , reference.getStamp()+<span class="number">1</span>));</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;).start();</span><br><span class="line"></span><br><span class="line">		<span class="comment">//第二个线程等待第一个线程执行完</span></span><br><span class="line">        <span class="keyword">new</span> Thread(()-&gt;&#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">int</span> stamp = reference.getStamp();</span><br><span class="line">                <span class="comment">//假设执行到这里发生上下文切换</span></span><br><span class="line">                System.out.println(<span class="string">&quot;Before sleep:stamp=&quot;</span>+stamp);</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">5</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;After sleep:stamp=&quot;</span>+reference.getStamp());</span><br><span class="line">                <span class="keyword">boolean</span> b = reference.compareAndSet(<span class="number">100</span>, <span class="number">101</span>, stamp, stamp + <span class="number">1</span>);</span><br><span class="line">                System.out.println(b);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">	Before sleep:stamp=0</span></span><br><span class="line"><span class="comment">	t1 true</span></span><br><span class="line"><span class="comment">	1,101</span></span><br><span class="line"><span class="comment">	t1 true</span></span><br><span class="line"><span class="comment">	After sleep:stamp=2</span></span><br><span class="line"><span class="comment">	false</span></span><br><span class="line"><span class="comment">**/</span></span><br></pre></td></tr></table></figure>

<p>结果肯定是t2执行失败了，毕竟戳不一样了，就算引用一样也没用。</p>
<h4 id="小插曲-Integer缓存"><a href="#小插曲-Integer缓存" class="headerlink" title="小插曲(Integer缓存)"></a>小插曲(Integer缓存)</h4><p>这里一开始发生了一个小插曲，首先这里是的引用类型是 <code>Integer</code>类型的，然后我在进行CAS的时候从100—&gt;200 ,然后又从200–&gt;100，可能细心的朋友已经知道啥问题了，后面的从200–&gt;100会失败，为啥？这个200和前面的200不是一个对象，引用不一样，那为啥101就可以呢？对，Integer有一个缓冲池，大小在-128–127之间的数，可以直接从缓冲池中拿，我开始在这里纠结了好一会儿😂</p>
<h3 id="字段更新器"><a href="#字段更新器" class="headerlink" title="字段更新器"></a>字段更新器</h3><p>如果我们只需要某个类里的某个字段，也就是说让普通的变量也享受原子操作，可以使用原子更新字段类，如在某些时候由于项目前期考虑不周全，项目需求又发生变化，使得某个类中的变量需要执行多线程操作，由于该变量多处使用，改动起来比较麻烦，而且原来使用的地方无需使用线程安全，只要求新场景需要使用时，可以借助原子更新器处理这种场景，Java中提供了几种字段更新器<code>AtomicIntegerFieldUpdater</code>，<code>AtomicLongFieldUpdater</code>，<code>AtomicReferenceFieldUpdater</code>，看名字就知道是对应啥的</p>
<h4 id="AtomicIntegerFieldUpdater测试"><a href="#AtomicIntegerFieldUpdater测试" class="headerlink" title="AtomicIntegerFieldUpdater测试"></a>AtomicIntegerFieldUpdater测试</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AtomicIntegerFieldUpdaterTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        AtomicIntegerFieldUpdater updater = AtomicIntegerFieldUpdater.newUpdater(TestUpdate.class, <span class="string">&quot;num&quot;</span>);</span><br><span class="line">        TestUpdate testUpdate = <span class="keyword">new</span> TestUpdate();</span><br><span class="line">        Stream.of(<span class="string">&quot;t1&quot;</span>, <span class="string">&quot;t2&quot;</span>, <span class="string">&quot;t3&quot;</span>, <span class="string">&quot;t4&quot;</span>, <span class="string">&quot;t5&quot;</span>).forEach(s -&gt; &#123;</span><br><span class="line">            <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">                <span class="keyword">int</span> MAX = <span class="number">100</span>;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; MAX; i++) &#123;</span><br><span class="line">                    System.out.println(updater.getAndIncrement(testUpdate));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;, s).start();</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">TestUpdate</span> </span>&#123;</span><br><span class="line">        <span class="keyword">volatile</span> <span class="keyword">int</span> num;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样就保证了Integer字段自增操作的原子性，另外两个与之类似。</p>
<p><strong>需要注意的地方</strong></p>
<ul>
<li><p>操作的字段不能是static类型。</p>
</li>
<li><p>操作的字段不能是final类型的，因为final根本没法修改。</p>
</li>
<li><p>字段必须是volatile修饰的，也就是数据本身是读一致的。</p>
</li>
<li><p>属性必须对当前的Updater所在的区域是可见的，也就是说无论何时都应该保证操作类与被操作类间的可见性。</p>
</li>
</ul>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top///20190430/hIuzU4rePaAe.png?imageslim"
                      alt="mark"
                ></p>
<blockquote>
<p>使用字段更新器比起直接使用原子类要节约内存，但是操作起来不方便</p>
</blockquote>
<h2 id="Unsafe双刃剑"><a href="#Unsafe双刃剑" class="headerlink" title="Unsafe双刃剑"></a>Unsafe双刃剑</h2><p><strong>Unsafe</strong>类，看名字就知道不安全，并不是它写的不安全，而是用起来不安全，因为它可以像c/c++一样去操作内存地址，<strong>unsafe</strong>里面的所有方法都是<strong>native</strong>的，底层都是c/c++实现的，直接与操作系统底层交互，上面CAS执行也依赖于<strong>unsafe</strong>类中的方法，其实整个并发包里的类都依赖于<strong>unsafe</strong>，但是官方并不建议用户使用这个类</p>
<ul>
<li>Unsafe有可能在未来的Jdk版本移除或者不允许Java应用代码使用，这一点可能导致使用了Unsafe的应用无法运行在高版本的Jdk</li>
<li>Unsafe的不少方法中必须提供原始地址(内存地址)和被替换对象的地址，偏移量要自己计算，一旦出现问题就是JVM崩溃级别的异常，会导致整个JVM实例崩溃，表现为应用程序直接崩掉。</li>
<li>Unsafe提供的直接内存访问的方法中使用的内存不受JVM管理(无法被GC)，需要手动管理，一旦出现疏忽很有可能成为内存泄漏的源头。</li>
</ul>
<h3 id="获取Unsafe"><a href="#获取Unsafe" class="headerlink" title="获取Unsafe"></a>获取Unsafe</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//获取Unsafe</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Unsafe <span class="title">getUnsafe</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    Field f = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        f = Unsafe.class.getDeclaredField(<span class="string">&quot;theUnsafe&quot;</span>);</span><br><span class="line">        f.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">        <span class="keyword">return</span> (Unsafe)f.get(<span class="keyword">null</span>);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="CAS相关"><a href="#CAS相关" class="headerlink" title="CAS相关"></a>CAS相关</h3><p>Java中的CAS实现调用的就是三个本地方法，第一个参数代表的就是实例对象，第二个参数代表需要CAS字段在该实例上的偏移量（不用自己计算，Unsafe提供了方法计算偏移量），第三个参数就是期望值，最后一个参数就是更新的值</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">compareAndSwapObject</span><span class="params">(Object var1, <span class="keyword">long</span> var2, Object var4, Object var5)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">compareAndSwapInt</span><span class="params">(Object var1, <span class="keyword">long</span> var2, <span class="keyword">int</span> var4, <span class="keyword">int</span> var5)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">compareAndSwapLong</span><span class="params">(Object var1, <span class="keyword">long</span> var2, <span class="keyword">long</span> var4, <span class="keyword">long</span> var6)</span></span>;</span><br></pre></td></tr></table></figure>

<h3 id="利用Unsafe自己写一个原子Counter"><a href="#利用Unsafe自己写一个原子Counter" class="headerlink" title="利用Unsafe自己写一个原子Counter"></a>利用Unsafe自己写一个原子Counter</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CASCounter</span> <span class="keyword">implements</span> <span class="title">Counter</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">long</span> counter = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">CASCounter</span><span class="params">()</span> <span class="keyword">throws</span> NoSuchFieldException </span>&#123;</span><br><span class="line">        unsafe = getUnsafe();</span><br><span class="line">        <span class="comment">//获取counter字段的内存偏移量</span></span><br><span class="line">        offset= unsafe.objectFieldOffset(CASCounter.class.getDeclaredField(<span class="string">&quot;counter&quot;</span>));</span><br><span class="line">        System.out.println(offset);</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">private</span> Unsafe unsafe;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">long</span> offset;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Unsafe <span class="title">getUnsafe</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Field f = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            f = Unsafe.class.getDeclaredField(<span class="string">&quot;theUnsafe&quot;</span>);</span><br><span class="line">            f.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">            <span class="keyword">return</span> (Unsafe)f.get(<span class="keyword">null</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">increment</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> current=counter;</span><br><span class="line">        <span class="keyword">while</span> (!unsafe.compareAndSwapLong(<span class="keyword">this</span>,offset,current,current+<span class="number">1</span>))&#123;</span><br><span class="line">            current=counter;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">long</span> <span class="title">getCounter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> counter;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Counter</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">increment</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">long</span> <span class="title">getCounter</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Unsafe的骚操作"><a href="#Unsafe的骚操作" class="headerlink" title="Unsafe的骚操作"></a>Unsafe的骚操作</h3><p><strong>绕过构造器创建对象</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UnsafeFooTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException,InstantiationException, NoSuchFieldException </span>&#123;</span><br><span class="line">        Unsafe unsafe = UnsafeTest.getUnsafe();</span><br><span class="line">        <span class="comment">//绕过构造器创建对象</span></span><br><span class="line">        Simple simple = (Simple) unsafe.allocateInstance(Simple.class);</span><br><span class="line">        System.out.println(simple.get()); <span class="comment">//null</span></span><br><span class="line">        System.out.println(simple.getClass().getClassLoader());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Simple</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> String a = <span class="string">&quot;a&quot;</span>;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Simple</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            a = <span class="string">&quot;new&quot;</span>;</span><br><span class="line">            System.out.println(<span class="string">&quot;============== &quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> String <span class="title">get</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> a;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">static</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;静态代码块&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>修改字段在内存中的值</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UnsafeFooTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException, InstantiationException, NoSuchFieldException </span>&#123;</span><br><span class="line">        Unsafe unsafe = UnsafeTest.getUnsafe();</span><br><span class="line">        Permission permission = <span class="keyword">new</span> Permission();</span><br><span class="line">        permission.doSth();</span><br><span class="line">        <span class="comment">//通过反射也可以做到，但是unsafe直接是到内存地址中将值修改了</span></span><br><span class="line">        Field access_allow = permission.getClass().getDeclaredField(<span class="string">&quot;ACCESS_ALLOW&quot;</span>);</span><br><span class="line">        <span class="comment">//获取字段再对象中的内存偏移量，可以简单理解为指针（内存地址）</span></span><br><span class="line">        unsafe.putLong(permission,unsafe.objectFieldOffset(access_allow),-<span class="number">1</span>);</span><br><span class="line">        permission.doSth();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Permission</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> ACCESS_ALLOW = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">boolean</span> <span class="title">isAllow</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span>  ACCESS_ALLOW==-<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">doSth</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (isAllow()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;i am workind&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>defindClass加载类文件</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UnsafeFooTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException, InstantiationException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException </span>&#123;</span><br><span class="line">        Unsafe unsafe = UnsafeTest.getUnsafe();</span><br><span class="line">        <span class="keyword">byte</span>[] bytes = loadClassContent();</span><br><span class="line">        Class&lt;?&gt; aClass = unsafe.defineClass(<span class="keyword">null</span>, bytes, <span class="number">0</span>, bytes.length, ClassLoader.getSystemClassLoader(), <span class="keyword">null</span>);</span><br><span class="line">        <span class="keyword">int</span> get = (<span class="keyword">int</span>) aClass.getMethod(<span class="string">&quot;get&quot;</span>).invoke(aClass.newInstance(), <span class="keyword">null</span>);</span><br><span class="line">        System.out.println(get);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//将class字节码加载到内存中</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">byte</span>[] loadClassContent() &#123;</span><br><span class="line">        File f = <span class="keyword">new</span> File(<span class="string">&quot;D:\\ClassLoaderTest\\Res.class&quot;</span>);</span><br><span class="line">        FileInputStream stream = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">byte</span>[] bytes=<span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            stream = <span class="keyword">new</span> FileInputStream(f);</span><br><span class="line">             bytes = <span class="keyword">new</span> <span class="keyword">byte</span>[(<span class="keyword">int</span>) f.length()];</span><br><span class="line">            stream.read(bytes);</span><br><span class="line">            stream.close();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> bytes;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>将编译好的class文件放到对应的目录下</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Res</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> i=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Res</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.i=<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">get</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>结果</strong>，是不是很牛皮？🐂🍺是🐂🍺但是这个玩意尽量的别用。。</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190720/zLJJUhQ6GAdc.png?imageslim"
                      alt="mark"
                ></p>
<p><strong>Unsafe</strong>里面的方法还有很多这里就不都列举了，毕竟暂时还用不到，如果想了解更多可以看看这几篇文章</p>
<ul>
<li><p><a class="link"   target="_blank" rel="noopener" href="https://www.cnblogs.com/throwable/p/9139947.html" >JAVA中神奇的双刃剑–Unsafe<i class="fas fa-external-link-alt"></i></a></p>
</li>
<li><p><a class="link"   target="_blank" rel="noopener" href="https://www.zhihu.com/question/29266773?sort=created" >R大关于Unsafe的使用建议<i class="fas fa-external-link-alt"></i></a></p>
</li>
<li><p><a class="link"   target="_blank" rel="noopener" href="https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html" >Java魔法类：Unsafe应用解析<i class="fas fa-external-link-alt"></i></a></p>
</li>
</ul>

        </div>

        
            <div class="post-copyright-info">
                <div class="article-copyright-info-container">
    <ul>
        <li>本文标题：CAS与原子变量</li>
        <li>本文作者：Resolmi</li>
        <li>创建时间：2019-04-22 00:00:00</li>
        <li>
            本文链接：https://imlgw.top/2019/04/22/2c91a79/
        </li>
        <li>
            版权声明：本博客所有文章除特别声明外，均采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">BY-NC-SA</a> 许可协议。转载请注明出处！
        </li>
    </ul>
</div>

            </div>
        

        
            <div class="article-nav">
                
                    <div class="article-prev">
                        <a class="prev"
                           rel="prev"
                           href="/2019/04/29/1b898227/"
                        >
                            <span class="left arrow-icon flex-center">
                              <i class="fas fa-chevron-left"></i>
                            </span>
                            <span class="title flex-center">
                                <span class="post-nav-title-item">Volatile关键字详解</span>
                                <span class="post-nav-item">上一篇</span>
                            </span>
                        </a>
                    </div>
                
                
                    <div class="article-next">
                        <a class="next"
                           rel="next"
                           href="/2019/04/09/22c0ee69/"
                        >
                            <span class="title flex-center">
                                <span class="post-nav-title-item">Java多线程之设计模式</span>
                                <span class="post-nav-item">下一篇</span>
                            </span>
                            <span class="right arrow-icon flex-center">
                              <i class="fas fa-chevron-right"></i>
                            </span>
                        </a>
                    </div>
                
            </div>
        

        
            <div class="comment-container">
                <div class="comments-container">
    <div id="comment-anchor"></div>
    <div class="comment-area-title">
        <i class="fas fa-comments">&nbsp;评论</i>
    </div>
    

        
            <section class="disqus-comments">
<div id="disqus_thread">
  <noscript>Please enable JavaScript to view the <a target="_blank" rel="noopener" href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
</section>

<script>
var disqus_shortname = 'imlgw';

var disqus_url = 'https://imlgw.top/2019/04/22/2c91a79/';

(function(){
  var dsq = document.createElement('script');
  dsq.type = 'text/javascript';
  dsq.async = true;
  dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>

<script id="dsq-count-scr" src="//imlgw.disqus.com/count.js" async></script>
        
    
</div>

            </div>
        
    </div>
</div>


                
            </div>

        </div>

        <div class="page-main-content-bottom">
            <footer class="footer">
    <div class="info-container">
        <div class="copyright-info info-item">
            &copy;
            
              <span>2018</span>&nbsp;-&nbsp;
            
            2021&nbsp;<i class="fas fa-heart icon-animate"></i>&nbsp;<a href="/">Resolmi</a>
        </div>
        
            <script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="website-count info-item">
                
                    <span id="busuanzi_container_site_uv">
                        访问人数&nbsp;<span id="busuanzi_value_site_uv"></span>&ensp;
                    </span>
                
                
                    <span id="busuanzi_container_site_pv">
                        总访问量&nbsp;<span id="busuanzi_value_site_pv"></span>
                    </span>
                
            </div>
        
        
            <div class="icp-info info-item"><a target="_blank" rel="nofollow" href="https://beian.miit.gov.cn">鄂ICP备18011208号</a></div>
        
    </div>
</footer>

        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="tools-list">
        <!-- TOC aside toggle -->
        
            <li class="tools-item page-aside-toggle">
                <i class="fas fa-outdent"></i>
            </li>
        

        <!-- go comment -->
        
            <li class="go-comment">
                <i class="fas fa-comment"></i>
            </li>
        
    </ul>
</div>

        </div>
    

    <div class="right-bottom-side-tools">
        <div class="side-tools-container">
    <ul class="side-tools-list">
        <li class="tools-item tool-font-adjust-plus flex-center">
            <i class="fas fa-search-plus"></i>
        </li>

        <li class="tools-item tool-font-adjust-minus flex-center">
            <i class="fas fa-search-minus"></i>
        </li>

        <li class="tools-item tool-expand-width flex-center">
            <i class="fas fa-arrows-alt-h"></i>
        </li>

        <li class="tools-item tool-dark-light-toggle flex-center">
            <i class="fas fa-moon"></i>
        </li>

        <!-- rss -->
        

        

        <li class="tools-item tool-scroll-to-bottom flex-center">
            <i class="fas fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="exposed-tools-list">
        <li class="tools-item tool-toggle-show flex-center">
            <i class="fas fa-cog fa-spin"></i>
        </li>
        
            <li class="tools-item tool-scroll-to-top flex-center">
                <i class="arrow-up fas fa-arrow-up"></i>
                <span class="percent"></span>
            </li>
        
    </ul>
</div>

    </div>

    
        <aside class="page-aside">
            <div class="post-toc-wrap">
    <div class="post-toc">
        <ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#CAS"><span class="nav-number">1.</span> <span class="nav-text">CAS</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8E%9F%E5%AD%90%E5%8F%98%E9%87%8F%E7%B1%BB"><span class="nav-number">2.</span> <span class="nav-text">原子变量类</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A9%E7%94%A8CAS%E5%86%99%E4%B8%80%E4%B8%AA%E9%94%81"><span class="nav-number">2.1.</span> <span class="nav-text">利用CAS写一个锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ABA%E9%97%AE%E9%A2%98"><span class="nav-number">2.2.</span> <span class="nav-text">ABA问题</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%97%A0%E6%B3%95%E6%8E%A5%E5%8F%97%E7%9A%84%E4%BE%8B%E5%AD%90"><span class="nav-number">2.2.1.</span> <span class="nav-text">无法接受的例子</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3ABA%E9%97%AE%E9%A2%98"><span class="nav-number">2.2.2.</span> <span class="nav-text">如何解决ABA问题</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%8F%E6%8F%92%E6%9B%B2-Integer%E7%BC%93%E5%AD%98"><span class="nav-number">2.2.3.</span> <span class="nav-text">小插曲(Integer缓存)</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%97%E6%AE%B5%E6%9B%B4%E6%96%B0%E5%99%A8"><span class="nav-number">2.3.</span> <span class="nav-text">字段更新器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#AtomicIntegerFieldUpdater%E6%B5%8B%E8%AF%95"><span class="nav-number">2.3.1.</span> <span class="nav-text">AtomicIntegerFieldUpdater测试</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Unsafe%E5%8F%8C%E5%88%83%E5%89%91"><span class="nav-number">3.</span> <span class="nav-text">Unsafe双刃剑</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%8E%B7%E5%8F%96Unsafe"><span class="nav-number">3.1.</span> <span class="nav-text">获取Unsafe</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#CAS%E7%9B%B8%E5%85%B3"><span class="nav-number">3.2.</span> <span class="nav-text">CAS相关</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A9%E7%94%A8Unsafe%E8%87%AA%E5%B7%B1%E5%86%99%E4%B8%80%E4%B8%AA%E5%8E%9F%E5%AD%90Counter"><span class="nav-number">3.3.</span> <span class="nav-text">利用Unsafe自己写一个原子Counter</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Unsafe%E7%9A%84%E9%AA%9A%E6%93%8D%E4%BD%9C"><span class="nav-number">3.4.</span> <span class="nav-text">Unsafe的骚操作</span></a></li></ol></li></ol>
    </div>
</div>
        </aside>
    

    <div class="image-viewer-container">
    <img src="">
</div>


    
        <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
          <span class="search-input-field-pre">
            <i class="fas fa-keyboard"></i>
          </span>
            <div class="search-input-container">
                <input autocomplete="off"
                       autocorrect="off"
                       autocapitalize="off"
                       placeholder="搜索..."
                       spellcheck="false"
                       type="search"
                       class="search-input"
                >
            </div>
            <span class="popup-btn-close">
                <i class="fas fa-times"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fas fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>

    

</main>



<script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/utils.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/main.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/header-shrink.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/back2top.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/dark-light-toggle.js"></script>


    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/local-search.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/code-copy.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/lazyload.js"></script>


<div class="post-scripts pjax">
    
        <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/left-side-toggle.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/libs/anime.min.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/toc.js"></script>
    
</div>


    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/libs/pjax.min.js"></script>
<script>
    window.addEventListener('DOMContentLoaded', () => {
        window.pjax = new Pjax({
            selectors: [
                'head title',
                '.page-container',
                '.pjax'
            ],
            history: true,
            debug: false,
            cacheBust: false,
            timeout: 0,
            analytics: false,
            currentUrlFullReload: false,
            scrollRestoration: false,
            // scrollTo: true,
        });

        document.addEventListener('pjax:send', () => {
            KEEP.utils.pjaxProgressBarStart();
        });

        document.addEventListener('pjax:complete', () => {
            KEEP.utils.pjaxProgressBarEnd();
            window.pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
            KEEP.refresh();
        });
    });
</script>



<script src="https://cdn.jsdelivr.net/npm/live2d-widget@3.x/lib/L2Dwidget.min.js"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"https://cdn.jsdelivr.net/npm/live2d-widget-model-hijiki@1.0.5/assets/hijiki.model.json"},"display":{"superSample":2,"width":160,"height":320,"position":"right","hOffset":0,"vOffset":-70},"mobile":{"show":false,"scale":0.2},"log":false});</script></body>
</html>
